package oop.core.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
//import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import oop.core.control.Controller;
/**
 * This class is the menu which can be invoked in order
 * to change the keys to the user's preference. It does
 * this by creating a hashmap then replacing the keyMap
 * in the Controller with the new hashmap. The commented 
 * out code refers to code that might have been used to
 * allow the user to invoke shift, control, or alter in 
 * order to equip, unequip, or drop items.
 * 
 * @author Stephanie + Alex Guthrie
 *
 */

public class ControllerConfigMenu extends JPanel implements PropertyChangeListener, KeyListener{

	public static final String ID = "CONTROLLER_CONFIG_MENU";
	private final Dimension SIZE = new Dimension(1000,820);
	private final Point LOCATION = new Point(0, 0);
	
	private JFormattedTextField[] fields;
	private char[] values;
	/*
	 * index 0 == pause
	 * index 1 == southwest
	 * index 2 == south
	 * index 3 == southeast
	 * index 4 == west
	 * index 5 == 0 (dummy value)
	 * index 6 == east
	 * index 7 == northwest
	 * index 8 == north
	 * index 9 == northeast
	 */
	
	private JButton cancelButton;
	private JButton saveButton;
	private JButton resetButton;
	private JButton acceptButton;
	private JButton loadButton;
	
    //private String[] equipOptions = {"CTRL", "ALT", "SHIFT"};
    //private String[] dropOptions = {"CTRL", "ALT", "SHIFT"};
	
	//controls
	//Labels to identify the fields
	private JLabel northwestLabel;
    private JLabel northLabel;
    private JLabel northeastLabel;
    private JLabel westLabel;
    private JLabel eastLabel;
    private JLabel southwestLabel;
    private JLabel southLabel;
    private JLabel southeastLabel;
    private JLabel pauseLabel;
    //private JLabel equipLabel;
    //private JLabel dropLabel;
	
    //Strings for the Labels
    private static String northwestString = "Move Northwest";
    private static String northString = "Move North";
    private static String northeastString = "Move Northeast";
    private static String westString = "Move West";
    private static String eastString = "Move East";
    private static String southwestString = "Move Southwest";
    private static String southString = "Move South";
    private static String southeastString = "Move Southeast";
    private static String pauseString = "Pause Game";
    //private static String equipString = "Equip Items";
    //private static String dropString = "Drop Items";
    
	private JFormattedTextField northwestField;
	private JFormattedTextField northField;
	private JFormattedTextField northeastField;
	private JFormattedTextField westField;
	private JFormattedTextField eastField;
	private JFormattedTextField southwestField;
	private JFormattedTextField southField;
	private JFormattedTextField southeastField;
	private JFormattedTextField pauseField;
	//private JComboBox equipField;
	//private JComboBox dropField;
	
	/**
	 * Constructor: initializes all the fields and lays them out in a BorderLayout
	 *
	 * @param keyMap
	 */
	

	public ControllerConfigMenu()
	{
		this.setLayout(new BorderLayout());
		values = new char[10];
		
		this.setLocation(LOCATION);
		this.setSize(SIZE);
		//this.setVisible(true);
		this.setFocusable(true);
		JPanel buttonPane = new JPanel();
		buttonPane.setLayout(new GridLayout(1,3));
		
		 acceptButton = new JButton("Accept");
         acceptButton.setVisible(true);
         buttonPane.add(acceptButton);
         
         loadButton = new JButton("Load");
         loadButton.setVisible(true);
         buttonPane.add(loadButton);
         
         saveButton = new JButton("Save");
         saveButton.setVisible(true);
         buttonPane.add(saveButton);
         
         resetButton = new JButton("Reset");
         resetButton.setVisible(true);
         buttonPane.add(resetButton);
         
         cancelButton = new JButton("Cancel");
         cancelButton.setVisible(true);
         buttonPane.add(cancelButton);
		
		//Create the labels.
        northwestLabel = new JLabel(northwestString + "  ", JLabel.RIGHT);
        northLabel = new JLabel(northString + "  ", JLabel.RIGHT);
        northeastLabel = new JLabel(northeastString + "  ", JLabel.RIGHT);
        westLabel = new JLabel(westString + "  ", JLabel.RIGHT);
        eastLabel = new JLabel(eastString + "  ", JLabel.RIGHT);
        southwestLabel = new JLabel(southwestString + "  ", JLabel.RIGHT);
        southLabel = new JLabel(southString + "  ", JLabel.RIGHT);
        southeastLabel = new JLabel(southeastString + "  ", JLabel.RIGHT);
        pauseLabel = new JLabel(pauseString + "  ", JLabel.RIGHT);

        //Create the text fields and set them up.
        northwestField = new JFormattedTextField();
        northwestField.setValue(values[7]);
        northwestField.setColumns(20);
        northwestField.addPropertyChangeListener("value", this);
        northwestField.addKeyListener(this);

        northField = new JFormattedTextField();
        northField.setValue(values[8]);
        northField.addPropertyChangeListener("value", this);
        northField.addKeyListener(this);

        northeastField = new JFormattedTextField();
        northeastField.setValue(values[9]);
        northeastField.addPropertyChangeListener("value", this);
        northeastField.addKeyListener(this);

        westField = new JFormattedTextField();
        westField.setValue(values[4]);
        westField.addPropertyChangeListener("value", this);
        westField.addKeyListener(this);
        
        eastField = new JFormattedTextField();
        eastField.setValue(values[6]);
        eastField.addKeyListener(this);
        eastField.addPropertyChangeListener("value", this);
        
        southwestField = new JFormattedTextField();
        southwestField.setValue(values[1]);
        southwestField.addKeyListener(this);
        southwestField.addPropertyChangeListener("value", this);
        
        southField = new JFormattedTextField();
        southField.setValue(values[2]);
        southField.addKeyListener(this);
        southField.addPropertyChangeListener("value", this);
        
        southeastField = new JFormattedTextField();
        southeastField.setValue(values[3]);
        southeastField.addKeyListener(this);
        southeastField.addPropertyChangeListener("value", this);
        
        pauseField = new JFormattedTextField();
        pauseField.setValue(values[0]);
        pauseField.addKeyListener(this);
        pauseField.addPropertyChangeListener("value", this);
        
        fields = new JFormattedTextField[10];
        fields[7] = northwestField;
        fields[8] = northField;
        fields[9] = northeastField;
        fields[4] = westField;
        fields[6] = eastField;
        fields[1] = southwestField;
        fields[2] = southField;
        fields[3] = southeastField;
        fields[0] = pauseField;
        
        //Tell accessibility tools about label/textfield pairs.
        northwestLabel.setLabelFor(northwestField);
        northLabel.setLabelFor(northField);
        northeastLabel.setLabelFor(northeastField);
        westLabel.setLabelFor(westField);
        eastLabel.setLabelFor(eastField);
        southwestLabel.setLabelFor(southwestField);
        southLabel.setLabelFor(southField);
        southeastLabel.setLabelFor(southeastField);
        pauseLabel.setLabelFor(pauseField);

        //Lay out the labels in a panel.        
        
        JPanel labelPane = new JPanel(new GridLayout(0,1));
        labelPane.add(northwestLabel);
        labelPane.add(northLabel);
        labelPane.add(northeastLabel);
        labelPane.add(westLabel);
        labelPane.add(eastLabel);
        labelPane.add(southwestLabel);
        labelPane.add(southLabel);
        labelPane.add(southeastLabel);
        labelPane.add(pauseLabel);

        //Layout the text fields in a panel.
        JPanel fieldPane = new JPanel(new GridLayout(0,1));
        fieldPane.add(northwestField);
        fieldPane.add(northField);
        fieldPane.add(northeastField);
        fieldPane.add(westField);
        fieldPane.add(eastField);
        fieldPane.add(southwestField);
        fieldPane.add(southField);
        fieldPane.add(southeastField);
        fieldPane.add(pauseField);

        //Put the panels in this panel, labels on left,
        //text fields on right.
        labelPane.setVisible(true);
        fieldPane.setVisible(true);
        
        JPanel completePane = new JPanel(new GridLayout(1,2));
        completePane.add(labelPane);
        completePane.add(fieldPane);
        completePane.setVisible(true);
        
        this.add(buttonPane, BorderLayout.WEST);
        this.add(labelPane, BorderLayout.CENTER);
        this.add(fieldPane, BorderLayout.EAST);
        
        for(int k=0; k<fields.length; k++)
        {
        	if(fields[k] == null)
        		continue;
        	fields[k].setText("");
        }
	}
	
	/**
	 * Set Default values in textFields
	 */
	private void setDefault() {
		values[0] = 'p';
		values[1] = '1';
		values[2] = '2';
		values[3] = '3';
		values[4] = '4';
		values[5] = '0';
		values[6] = '6';
		values[7] = '7';
		values[8] = '8';
		values[9] = '9';
	}
	
	public Map<Character, Integer> getNewConfig()
	{
		Map<Character, Integer> config = new HashMap<Character, Integer>();
		
		for(Integer i : Controller.ALL_MOVE_DIRECTIONS)
		{
			config.put(getCharOfField(i),i);
		}
		
		return config;
	}
	
	/**
	 * This method fills all the textfields with the 
	 * initial values.
	 */
	public void resetMenu() {
		for(int k=0; k<=9; k++)
		{
			if(k==5)
				continue;
			fields[k].setText("");
		}
	}
	
	public void setConfig(Map<Character, Integer> config)
	{
		System.out.println("Setting config: " + config);
		for(Character c : config.keySet())
		{
			fields[config.get(c)].setText(""+c);
		}
	}
	
	public boolean isValidConfig()
	{
		Set<Character> set = new HashSet<Character>();
		for(int k=0; k<=9; k++)
		{
			if(k==5)
				continue;
			if(fields[k].getText().length() == 0)
				return false;
			char c = getCharOfField(k);
			if(set.contains(c))
				return false;
			set.add(c);
		}
		return true;
	}
	
	private char getCharOfField(int i)
	{
		return fields[i].getText().toCharArray()[0];
	}
	
	/**
	 * Will Save the current configuration and take the user
	 * back to the pause menu
	 * @param listener
	 */
    public void addAcceptButtonListener(ActionListener listener)
    {
            acceptButton.addActionListener(listener);
    }
    
    public void addSaveButtonListener(ActionListener listener)
    {
            saveButton.addActionListener(listener);
    }
    
    public void addLoadButtonListener(ActionListener listener)
    {
            loadButton.addActionListener(listener);
    }
    
    public void addResetButtonListener(ActionListener listener)
    {
            resetButton.addActionListener(listener);
    }
    
    public void addCancelButtonListener(ActionListener listener)
    {
            cancelButton.addActionListener(listener);
    }
	
	/**
	 * Set a background color in the panel.
	 * @param g 
	 */
	/*
	protected void paintComponent(Graphics g)
	{
		g.setColor(Color.CYAN);
		g.fillRect(0, 0, SIZE.width, SIZE.height);
	}
	*/
	
	
	/**
	 * This method gets the character value of the typed
	 * input. If it is uppercase, this method makes it lowercase.
	 * This class will then use these values to create a hashmap
	 * when the user selects "Save"
	 * 
	 * @param e is the PropertyChangeEvent triggered by a
	 * person typing in any of the textfields
	 */
	public void propertyChange(PropertyChangeEvent e) {
		JFormattedTextField source = (JFormattedTextField) e.getSource();
		
		for ( int i = 0; i < 10; i++ ) {
			if ( i == 5 )
				i++;
			if ( source == fields[i] ) {
				values[i] = ((String) fields[i].getValue()).charAt(0);
				if ( values[i] >= 65 && values[i] <= 90 ) //make lowercase if uppercase
					values[i]+=32;			
				fields[i].setValue(Character.toString(values[i]));
				//checkIfExists(source,values[i]);
			}
		}
    }
	
	/**
	 * Checks if the character has already been chosen for another field.
	 * If it has, it changes the other field to a new value.
	 * @param source is the field that has been changed. Want to check every
	 * field except this one. Commented out because this wasn't working. At 
	 * runtime, the computer thinks that it is a String, and when changed, thinks 
	 * that it is a Character. Check is now performed in AcceptControllerConfigListener
	 * and SaveControllerConfigListener.
	 * @param c is the char that we are checking the others' against.
	 */ /*
	private void checkIfExists( JFormattedTextField source, char c ) {
		for ( int i = 0; i < 10; i++ ) {
			if ( i == 5 )
				i++;
			JFormattedTextField o = fields[i];
			System.out.println( fields[i].getValue() instanceof Character );
			if ( !o.equals(source) ) {
				char compare = ((String) o.getValue()).charAt(0);
				if ( compare == c ) //need to change compare
					o.setValue(Character.toString('/'));
			}
		}
	}
	*/
		
	/**
	 * returns the new hashmap so that the controller can
	 * replace the hashmap with the user-revised one
	 */
	public HashMap<Integer,Integer> newValues() {
		HashMap<Integer,Integer> ret = new HashMap<Integer,Integer>();
		for ( int i = 0; i < 10; i++ ) {
			if ( i == 5 )
				i++;
			if ( ret.containsKey((int)values[i]) ) {
				ret.put(-1, -1);
			}
			else {
				if ( i == 0 )
					ret.put((int)values[0],(int)'p');
				else
					ret.put((int)values[i], i);
			}
		}
		return ret;		
	}
	
	/**
	 * Allows the user to only input one key into each field
	 */
	@Override
	public void keyPressed(KeyEvent e) {
		JTextField source = (JTextField) e.getSource();
		source.setText("");
		e.consume();
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		//do nothing
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		//do nothing
	}
}